package za.org.jcicada.cfgmngr.impl.katcp;

import java.util.ArrayList;
import java.util.List;

import za.org.jcicada.cfgmngr.IPhysicalClient;
import za.org.jcicada.cfgmngr.SystemSetType;
import za.org.jcicada.cfgmngr.ISystemObserver.Event;
import za.org.jcicada.cfgmngr.messages.AttachReply;
import za.org.jcicada.cfgmngr.messages.AttachRequest;
import za.org.jcicada.cfgmngr.messages.DeregisterServiceReply;
import za.org.jcicada.cfgmngr.messages.DeregisterServiceRequest;
import za.org.jcicada.cfgmngr.messages.DeregisterSystemReply;
import za.org.jcicada.cfgmngr.messages.DeregisterSystemRequest;
import za.org.jcicada.cfgmngr.messages.DetachReply;
import za.org.jcicada.cfgmngr.messages.DetachRequest;
import za.org.jcicada.cfgmngr.messages.GetChildrenReply;
import za.org.jcicada.cfgmngr.messages.GetChildrenRequest;
import za.org.jcicada.cfgmngr.messages.GetConfigurationReply;
import za.org.jcicada.cfgmngr.messages.GetConfigurationRequest;
import za.org.jcicada.cfgmngr.messages.LocateServiceReply;
import za.org.jcicada.cfgmngr.messages.LocateServiceRequest;
import za.org.jcicada.cfgmngr.messages.NodeSystemsReply;
import za.org.jcicada.cfgmngr.messages.NodeSystemsRequest;
import za.org.jcicada.cfgmngr.messages.RegisterServiceReply;
import za.org.jcicada.cfgmngr.messages.RegisterServiceRequest;
import za.org.jcicada.cfgmngr.messages.RegisterSystemReply;
import za.org.jcicada.cfgmngr.messages.RegisterSystemRequest;
import za.org.jcicada.cfgmngr.messages.SensorSetReply;
import za.org.jcicada.cfgmngr.messages.SensorSetRequest;
import za.org.jcicada.cfgmngr.messages.ServiceSetReply;
import za.org.jcicada.cfgmngr.messages.ServiceSetRequest;
import za.org.jcicada.cfgmngr.messages.SystemEventInform;
import za.org.jcicada.cfgmngr.messages.SystemSetReply;
import za.org.jcicada.cfgmngr.messages.SystemSetRequest;
import za.org.jcicada.cfgmngr.messages.ViewEventInform;
import za.org.jcicada.cfgmngr.messages.ViewSensorInform;
import za.org.jcicada.cfgmngr.messages.ViewSensorsReply;
import za.org.jcicada.cfgmngr.messages.ViewSensorsRequest;
import za.org.jcicada.comms.impl.KatcpSerializerStrategy;
import za.org.jcicada.comms.messages.CommsMessage;
import za.org.jcicada.genss.PhysicalURN;

public class ConfigurationKatcpSerializer extends KatcpSerializerStrategy {

	public ConfigurationKatcpSerializer() {
		super(new Marshal(), new Unmarshal());
	}

	public static class Marshal {
		public Object[] AttachReply(AttachReply msg) {
			return new Object[] { msg.getCode(), msg.getMessage() };
		}

		public Object[] AttachRequest(AttachRequest msg) {
			return new Object[] {};
		}

		public Object[] DeregisterServiceReply(DeregisterServiceReply msg) {
			return new Object[] { msg.getCode(), msg.getMessage(), msg.getLocationURI(), msg.getServiceURN() };
		}
		
		public Object[] DeregisterServiceRequest(DeregisterServiceRequest msg) {
			return new Object[] { msg.getLocationURI(), msg.getServiceURN() };
		}

		public Object[] DeregisterSystemReply(DeregisterSystemReply msg) {
			return new Object[] { msg.getCode(), msg.getMessage(), msg.getSystemURN() };
		}

		public Object[] DeregisterSystemRequest(DeregisterSystemRequest msg) {
			return new Object[] { msg.getSystemURI() };
		}

		public Object[] DetachReply(DetachReply msg) {
			return new Object[] { msg.getCode(), msg.getMessage() };
		}

		public Object[] DetachRequest(DetachRequest msg) {
			return new Object[] {};
		}

		public Object[] GetChildrenReply(GetChildrenReply msg) {
			Object[] args = new Object[] { msg.getCode(), msg.getMessage(), msg.getParentURN() };
			return concatenate(args, getCollectionArray(msg.getChildrenURNs()));
		}
		
		public Object[] GetChildrenRequest(GetChildrenRequest msg) {
			return new Object[] { msg.getParentURN() };
		}
		
		public Object[] GetConfigurationReply(GetConfigurationReply msg) {
			return new Object[] { msg.getCode(), msg.getMessage(), msg.getConfiguration() };
		}
		
		public Object[] GetConfigurationRequest(GetConfigurationRequest msg) {
			return new Object[] { msg.getSubsystemURN() };
		}
		
		public Object[] LocateServiceReply(LocateServiceReply msg) {
			return new Object[] { msg.getCode(), msg.getMessage(), msg.getServiceURN(), msg.getLocationURI() };
		}
		
		public Object[] LocateServiceRequest(LocateServiceRequest msg) {
			return new Object[] { msg.getServiceURN(), msg.getProtocol() };
		}
		
		public Object[] NodeSystemsReply(NodeSystemsReply msg) {
			return concatenate(new Object[] { msg.getCode(), msg.getMessage(), msg.getPhysicalURN() },
					getCollectionArray(msg.getSystemURNs()));
		}
		
		public Object[] NodeSystemsRequest(NodeSystemsRequest msg) {
			return new Object[] { msg.getPhysicalURN() };
		}
		
		public Object[] RegisterServiceReply(RegisterServiceReply msg) {
			return new Object[] { msg.getCode(), msg.getMessage(), msg.getLocationURI(), msg.getServiceURN() };
		}
		
		public Object[] RegisterServiceRequest(RegisterServiceRequest msg) {
			return new Object[] { msg.getLocationURI(), msg.getServiceURN() };
		}
		
		public Object[] RegisterSystemReply(RegisterSystemReply msg) {
			return new Object[] { msg.getCode(), msg.getMessage(), msg.getSystemURN(), Boolean.toString(msg.getReregister()) };
		}
		
		public Object[] RegisterSystemRequest(RegisterSystemRequest msg) {
			return new Object[] { msg.getSystemURN() };
		}
		
		public Object[] SensorSetReply(SensorSetReply msg) {
			return concatenate(new Object[] { msg.getCode(), msg.getMessage(), msg.getSystemURN() }, 
					getCollectionArray(msg.getSensorURNs()));
		}
		
		public Object[] SensorSetRequest(SensorSetRequest msg) {
			return new Object[] { msg.getSystemURN() };
		}
		
		public Object[] ServiceSetReply(ServiceSetReply msg) {
			return concatenate(new Object[] { msg.getCode(), msg.getMessage(), msg.getSystemURN() },
					getCollectionArray(msg.getServiceURNs()));
		}
		
		public Object[] ServiceSetRequest(ServiceSetRequest msg) {
			return new Object[] { msg.getSystemURN() };
		}
		
		public Object[] SystemEventInform(SystemEventInform msg) {
			return new Object[] { msg.getSystemURN(), msg.getSystemSetType(), msg.getEvent() };
		}
		
		public Object[] SystemSetReply(SystemSetReply msg) {
			return concatenate(new Object[] { msg.getCode(), msg.getMessage(), msg.getType() },
					getCollectionArray(msg.getSystemURNs()));
		}
		
		public Object[] SystemSetRequest(SystemSetRequest msg) {
			return new Object[] { msg.getType() };
		}
		
		public Object[] ViewEventInform(za.org.jcicada.cfgmngr.messages.ViewEventInform msg) {
			return new Object[] { msg.getView(), msg.getEvent() };
		}
		
		public Object[] ViewSensorInform(ViewSensorInform msg) {
			return new Object[] { msg.getView(), msg.getPhysicalURN(), msg.getSensorURN() };
		}

		public Object[] ViewSensorsReply(ViewSensorsReply msg) {
			return new Object[] { msg.getCode(), msg.getMessage(), msg.getView(), msg.getNumber() };
		}
		
		public Object[] ViewSensorsRequest(ViewSensorsRequest msg) {
			return concatenate(new Object[] { msg.getView() },
					getCollectionArray(msg.getPhysicalURNs()));
		}
		
	}

	public static class Unmarshal {

		public List<PhysicalURN> getListPhysicalURN(String[] arg, int from) {
			List<PhysicalURN> urns = new ArrayList<PhysicalURN>();
			for (int i = from; i < arg.length; i++) {
				urns.add(parsePhysicalURN(arg, i));
			}
			return urns;
		}

		public CommsMessage AttachReply(String[] args) {
			return new AttachReply(parseResult(args));
		}

		public CommsMessage AttachRequest(String[] args) {
			return new AttachRequest();
		}
		
		public CommsMessage DeregisterServiceReply(String[] args) {
			return new DeregisterServiceReply(parseResult(args), parseURI(args, 2), parseServiceURN(args, 3));
		}
		
		public CommsMessage DeregisterServiceRequest(String[] args) {
			return new DeregisterServiceRequest(parseURI(args, 0), parseServiceURN(args, 1));
		}
		
		public CommsMessage DeregisterSystemReply(String[] args)  {
			return new DeregisterSystemReply(parseResult(args), parseSystemURN(args, 2));
		}
		
		public CommsMessage DeregisterSystemRequest(String[] args) {
			return new DeregisterSystemRequest(parseSystemURN(args, 0));
		}

		public CommsMessage DetachReply(String[] args) {
			return new DetachReply(parseResult(args));
		}

		public CommsMessage DetachRequest(String[] args) {
			return new DetachRequest();
		}

		public CommsMessage GetChildrenReply(String[] args)  {
			return new GetChildrenReply(parseResult(args), parsePhysicalURN(args, 2), getListPhysicalURN(args, 3));
		}

		public CommsMessage GetChildrenRequest(String[] args) {
			return new GetChildrenRequest(parsePhysicalURN(args, 0));
		}
		
		public CommsMessage GetConfigurationReply(String[] args) {
			return new GetConfigurationReply(parseResult(args), null);
		}
		
		public CommsMessage GetConfigurationRequest(String[] args) {
			return new GetConfigurationRequest(parseSystemURN(args, 0));
		}
		
		public CommsMessage LocateServiceReply(String[] args) {
			return new LocateServiceReply(parseResult(args), parseServiceURN(args, 2), parseURI(args, 3));
		}
		
		public CommsMessage LocateServiceRequest(String[] args) {
			return new LocateServiceRequest(parseServiceURN(args, 0), args[1]);
		}
		
		public CommsMessage NodeSystemsReply(String[] args) {
			return new NodeSystemsReply(parseResult(args), parsePhysicalURN(args, 2), getSetSystemURNs(args, 3));
		}
		
		public CommsMessage NodeSystemsRequest(String[] args) {
			return new NodeSystemsRequest(parsePhysicalURN(args, 0));
		}
		
		public CommsMessage RegisterServiceReply(String[] args) {
			return new RegisterServiceReply(parseResult(args), parseURI(args, 2), parseServiceURN(args, 3));
		}
		
		public CommsMessage RegisterServiceRequest(String[] args)  {
			return new RegisterServiceRequest(parseURI(args, 0), parseServiceURN(args, 1));
		}
		
		public CommsMessage RegisterSystemReply(String[] args) {
			return new RegisterSystemReply(parseResult(args), parseSystemURN(args, 2), Boolean.parseBoolean(args[3]));
		}
		
		public CommsMessage RegisterSystemRequest(String[] args) {
			return new RegisterSystemRequest(parseSystemURN(args, 0));
		}
		
		public CommsMessage SensorSetReply(String[] args) {
			return new SensorSetReply(parseResult(args), parseSystemURN(args, 2), getSetSensorURNs(args, 3));
		}
		
		public CommsMessage SensorSetRequest(String[] args) {
			return new SensorSetRequest(parseSystemURN(args, 0));
		}
		
		public CommsMessage ServiceSetReply(String[] args) {
			return new ServiceSetReply(parseResult(args), parseSystemURN(args, 2), getSetServiceURNs(args, 3));
		}
		
		public CommsMessage ServiceSetRequest(String[] args) {
			return new ServiceSetRequest(parseSystemURN(args, 0));
		}
		
		public CommsMessage SystemEventInform(String[] args) {
			return new SystemEventInform(parseSystemURN(args, 0), SystemSetType.valueOf(args[1]), Event.valueOf(args[2]));
		}
		
		public CommsMessage SystemSetReply(String[] args) {
			return new SystemSetReply(parseResult(args), SystemSetType.valueOf(args[2]), getSetSystemURNs(args, 3));
		}
		
		public CommsMessage SystemSetRequest(String[] args) {
			return new SystemSetRequest(SystemSetType.valueOf(args[0]));
		}
		
		public CommsMessage ViewEventInform(String[] args) {
			return new ViewEventInform(args[0], IPhysicalClient.Event.valueOf(args[1]));
		}
		
		public CommsMessage ViewSensorInform(String[] args) {
			return new ViewSensorInform(args[0], parsePhysicalURN(args, 1), parseSensorURN(args, 2));
		}
		
		public CommsMessage ViewSensorsReply(String[] args) {
			return new ViewSensorsReply(parseResult(args), args[2], Integer.parseInt(args[3]));
		}

		public CommsMessage ViewSensorsRequest(String[] args) {
			return new ViewSensorsRequest(args[0], getListPhysicalURN(args, 1));
		}
		
	}
}
